package org.jeecg.modules.system.aspect;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.alibaba.fastjson.JSON;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.IPUtils;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.modules.system.entity.SysLog;
import org.jeecg.modules.system.service.ISysLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * 系统日志，切面处理类
 *
 * @Author scott
 * @email jeecgos@163.com
 * @Date 2018年1月14日
 */
@Aspect
@Component
@Slf4j
public class AutoLogAspect {
    @Autowired
    private ISysLogService sysLogService;

    @Pointcut("@annotation(org.jeecg.common.aspect.annotation.AutoLog)")
    public void logPointCut() {

    }

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        //解决退出登陆后日志没有用户信息
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        //执行方法
        Object result = point.proceed();
        if (!(result instanceof Result)) {
            return result;
        }
        if (user == null) {
            user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        }
        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;
        try {
            //保存日志
            saveSysLog(point, time, (Result) result, user);
        }catch (Exception e){
            log.error(e.getMessage(), e);
        }
        return result;
    }

    private void saveSysLog(ProceedingJoinPoint joinPoint, long time, Result result, LoginUser user) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        SysLog sysLog = new SysLog();
        AutoLog syslog = method.getAnnotation(AutoLog.class);
        if (syslog == null) {
            return;
        }
        //注解上的描述,操作日志内容
        sysLog.setLogContent(syslog.value());
        sysLog.setLogType(syslog.logType());
        if (user == null) {
            user = new LoginUser();
            user.setRealname("游客");
        }
        String login = "login";
        if (StrUtil.equals(syslog.ty(), login)) {
            sysLog.setLogContent(result.getCode() == 200 ? user.getPhone() + "登陆成功" : user.getPhone() + "用户登陆失败");
        }
        sysLog.setUserid(user.getId());
        sysLog.setUsername(user.getRealname());
        sysLog.setCreateBy(user.getId());
        //请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        sysLog.setMethod(className + "." + methodName + "()");
        sysLog.setOperateType(StrUtil.isNotBlank(syslog.ty()) ? syslog.ty() : null);

        //获取request
        HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
        //请求的参数
        sysLog.setRequestParam(getReqestParams(request, joinPoint));
        sysLog.setRequestType(request.getMethod());
        UserAgent ua = UserAgentUtil.parse(request.getHeader("User-Agent"));
        sysLog.setUserAgent(ua.getBrowser().toString());
        //设置IP地址
        sysLog.setIp(IPUtils.getIpAddr(request));
        sysLog.setRequestUrl(request.getRequestURI());
        //获取登录用户信息
        sysLog.setUserid(user.getId());
        sysLog.setUsername(user.getRealname());
        sysLog.setCreateBy(user.getId());
        //耗时
        sysLog.setCostTime(time);
        sysLog.setCreateTime(new Date());
        //保存系统日志
        sysLogService.save(sysLog);
    }


    /**
     * @param request:   request
     * @param joinPoint: joinPoint
     * @Description: 获取请求参数
     * @author: scott
     * @date: 2020/4/16 0:10
     * @Return: java.lang.String
     */
    @SneakyThrows
    private String getReqestParams(HttpServletRequest request, JoinPoint joinPoint) {
        String httpMethod = request.getMethod();
        String params = "";
        String[] methods = {"POST", "PUT", "PATCH"};
        if (ArrayUtil.contains(methods, httpMethod)) {
            params = IoUtil.readUtf8(request.getInputStream());
        } else {
            params = JSON.toJSONString(request.getParameterMap());
        }
        return params;
    }
}
